﻿namespace CN2P.Web.Controllers.Api
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;
    using System.Web.Http;

    using CN2P.ServiceModel;

    public class ProductsApiController : BaseApiController
    {
        private static readonly object Sync = new object();

        private static readonly List<FullProductModel> Products = new List<FullProductModel>();

        static ProductsApiController()
        {
            var baseDir = HttpContext.Current.Server.MapPath("~/App_Data/Samples/Products");

            var imageBaseUrl = ConfigurationManager.AppSettings["ImageBaseUrl"];
            if (imageBaseUrl.EndsWith("/"))
            {
                imageBaseUrl = imageBaseUrl.Substring(0, imageBaseUrl.Length - 1);
            }

            foreach (var file in new DirectoryInfo(baseDir).GetFiles("*.json"))
            {
                var content = new StreamReader(file.FullName).ReadToEnd();
                var product = FullProductModel.FromJson(content);
                product.ProdId = GenerateId();

                if (!product.ImageUrl.StartsWith("/"))
                {
                    product.ImageUrl = "/" + product.ImageUrl;
                }

                product.ImageUrl = (imageBaseUrl + product.ImageUrl).ToLowerInvariant();
                Products.Add(product);
            }
        }

        [AcceptVerbs("GET")]
        public ProductModel Get(string prodId)
        {
            lock (Sync)
            {
                var product = Products.FirstOrDefault(item => item.ProdId == prodId);
                if (product == null)
                {
                    throw new HttpResponseException(this.NotFound("product-not-found", "Product is not found"));
                }

                var ratings = ReviewsApiController.Reviews.Where(item => item.ProdId == prodId).ToList();
                product.AvgRating = ratings.Count > 0 ? ratings.Average(item => item.Rating) : 0;

                return GetShortModel(product);
            }
        }


        [AcceptVerbs("GET")]
        public IDictionary<string, object> GetDetails(string prodId)
        {
            lock (Sync)
            {
                var product = Products.FirstOrDefault(item => item.ProdId == prodId);
                if (product == null)
                {
                    throw new HttpResponseException(this.NotFound("product-not-found", "Product is not found"));
                }

                var ratings = ReviewsApiController.Reviews.Where(item => item.ProdId == prodId).ToList();
                product.AvgRating = ratings.Count > 0 ? ratings.Average(item => item.Rating) : 0;

                return product.GetProps();
            }
        }

        [AcceptVerbs("GET")]
        public ProductModelPagedList GetItems(int pageSize = 10, int pageIndex = 0)
        {
            lock (Sync)
            {
                return Products
                    .Select(GetShortModel)
                    .ToList()
                    .ToPagedProductModel(pageIndex, pageSize);
            }
        }

        [AcceptVerbs("GET")]
        public ProductModelPagedList GetByTag(string key, int pageSize = 10, int pageIndex = 0)
        {
            lock (Sync)
            {
                return Products
                    .Where(item => item.HasTag(key))
                    .Select(GetShortModel)
                    .ToList()
                    .ToPagedProductModel(pageIndex, pageSize);
            }
        }

        [AcceptVerbs("GET")]
        public ProductModelPagedList GetByTerm(string key, int pageSize = 10, int pageIndex = 0)
        {
            lock (Sync)
            {
                return Products
                    .Where(item => item.HasTerm(key))
                    .Select(GetShortModel)
                    .ToList()
                    .ToPagedProductModel(pageIndex, pageSize);
            }
        }

        [AcceptVerbs("GET")]
        public IList<string> GetTags()
        {
            lock (Sync)
            {
                return Products
                    .Where(item => item.Tags != null)
                    .SelectMany(item => item.Tags)
                    .ToList()
                    .Distinct()
                    .OrderBy(item => item)
                    .ToList();
            }
        }

        [AcceptVerbs("DELETE")]
        public HttpResponseMessage Delete(string prodId)
        {
            lock (Sync)
            {
                var old = Products.FirstOrDefault(item => item.ProdId == prodId);
                if (old != null)
                {
                    Products.Remove(old);
                }
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        [AcceptVerbs("DELETE")]
        public HttpResponseMessage DeleteAll()
        {
            lock (Sync)
            {
                Products.Clear();
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        private static ProductModel GetShortModel(FullProductModel product)
        {
            return new ProductModel
            {
                prodId = product.ProdId,
                prodName = product.ProdName,
                imageUrl = product.ImageUrl,
                prodDesc = product.ProdDesc,
                prodPrice = product.ProdPrice,
                tags = product.Tags
            };
        }

        private static string GenerateId()
        {
            return Math.Abs(Guid.NewGuid().GetHashCode()).ToString();
        }
    }
}
